package com.jin.webvideo.service;

import com.jin.webvideo.base.util.CollectionsUtil;
import com.jin.webvideo.entity.Page;
import com.jin.webvideo.exception.TakenDownException;
import com.jin.webvideo.exception.UnavailableServiceException;
import com.jin.webvideo.exception.UnsupportServiceException;
import com.jin.webvideo.externalInterfaces.PlatformSupport;
import com.jin.webvideo.externalInterfaces.video.LocalApi;
import com.jin.webvideo.externalInterfaces.video.VideoAPI;
import com.jin.webvideo.base.spi.Interface;
import com.jin.webvideo.base.spi.Interfaces;
import com.jin.webvideo.base.spi.exception.InterfaceNotFoundException;
import com.jin.webvideo.base.spi.exception.InterfaceRunningException;
import com.jin.webvideo.externalInterfaces.entity.Filmography;
import com.jin.webvideo.util.entity.EntityUtil;
import com.jin.webvideo.util.consts.ConfigConst;
import com.jin.webvideo.util.sys.SqlUtil;
import com.jin.webvideo.util.base.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ApiService {
    private Map<String, VideoAPI> videoApis = new HashMap<>();
    @Autowired
    private ConfigService configService;

    // 通过AbstractVideoAPI注册
    public void registeVideoApi(String key, VideoAPI api){
        videoApis.put(key, api);
    }

    // 入configCache缓存，因为 列表的结果与配置有关，配置不变结果不变
    @Cacheable(cacheNames = "configCache", key = "'searchList'")
    public List<Map<String,String>> listSearchApi() throws InterfaceNotFoundException {
        Map<String, String> config = configService.configMapByGroupId(ConfigConst.SEARCH_CONFIG);
        Map<String, String> searchNames = configService.configMapByGroupId(ConfigConst.SEARCHNAME_CONFIG);
        String disable = config.getOrDefault(ConfigConst.ATTR_CONFIG_DISABLE, ConfigConst.CONFIG_EMPTY);
        String selected = config.getOrDefault(ConfigConst.ATTR_CONFIG_DEFAULT, ConfigConst.CONFIG_EMPTY);
        List<Map<String,String>> list = new ArrayList<>();
        for (String key : Interfaces.getProvider("search").installedInterfaceName()) {
            if (!SqlUtil.arrayContain(disable, key)) {
                Map<String, String> map = new HashMap<>();
                map.put("val", key);
                map.put("text", searchNames.getOrDefault(key, key));
                if (key.equals(selected)) {
                    list.add(0, map);
                    continue;
                }
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 搜索接口
     * @param platform
     * @param key
     * @param channel
     * @param page
     * @param pageSize
     * @return
     * @throws UnavailableServiceException
     */
    @Cacheable(cacheNames = "infoCache", key = "#platform + 'key_' + #key + '&page_' + #page", condition = "#platform != 'local'", unless="#result.allCount == 0")
    public Page<Filmography> search(String platform, String key, List<String> channel, int page, int pageSize) throws UnavailableServiceException{
        Interface i = null;
        try{
            i = Interfaces.parse("search", platform);
        }
        catch (InterfaceNotFoundException e) { }
        // 找不到相关的接口， 设配置的默认接口
        if (null == i) {
            platform = configService.configByGroupIdAndAttrid(ConfigConst.SEARCH_CONFIG, ConfigConst.ATTR_CONFIG_DEFAULT);
        }
        try{
            i = Interfaces.parse("search", platform);
            Page<Filmography> pageData = Interfaces.visit(i, key, "", String.valueOf(page), String.valueOf(pageSize));
            for (Filmography filmography : pageData.getList()){
                // 如果不存在id，则重设根据url重设id
                if (StringUtil.isEmpty(filmography.getId())){
                    String docid = EntityUtil.parseDocid(filmography);
                    filmography.setId(docid);
                }
            }
            // 去重
            CollectionsUtil.distinct(pageData.getList(), (item) -> item.getPlatform() + "-" + item.getId());
            if (!Page.isValid(pageData)) {
                pageData.getList().clear();
            }
            return pageData;
        } catch (InterfaceNotFoundException | InterfaceRunningException e) {
            e.printStackTrace();
            throw new UnavailableServiceException();
        }
    }

    /**
     * 热词接口
     * @param platform
     * @param key
     * @param count
     * @return
     * @throws UnavailableServiceException
     */
    @Cacheable(cacheNames = "infoCache", key = "'suggest_' + #key", condition = "#platform != 'local'")
    public List<String> suggest(String platform, String key, int count) throws UnavailableServiceException {
        try {
            Interface i = Interfaces.parse("recommand", platform);
            return Interfaces.visit(i, key, String.valueOf(count));
        } catch (InterfaceRunningException | InterfaceNotFoundException e) {
            e.printStackTrace();
           throw new UnavailableServiceException();
        }
    }

    /**
     * 获取视频及其所有的剧集基本信息 并设置当前播放视频
     * @param platform
     * @param docid
     * @param tvid
     * @return
     * @throws Exception
     */
    public Filmography getActiveVideoInformation(String platform, String docid, String tvid) throws Exception {
        Filmography filmography = getVideoInformation(platform, docid, tvid);
        VideoAPI api = assetCanGetVideoApi(platform);
        filmography = api.setActive(filmography, tvid);
        return filmography;
    }

    /**
     * 获取视频及其所有的剧集基本信息
     * @param platform
     * @param docid
     * @param tvid
     * @return
     * @throws UnavailableServiceException
     */
    @Cacheable(cacheNames = "infoCache", key = "'info_' + #platform+ '-' + #docid", condition = "#platform != 'local'")
    public Filmography getVideoInformation(String platform, String docid, String tvid) throws UnavailableServiceException {
        VideoAPI api = assetCanGetVideoApi(platform);
        Filmography filmography = null;
        try{
            filmography = api.baseInfoWithVideoInfoList(docid, tvid, 1, 10000);
        }
        catch (TakenDownException e) {
            throw e;
        }
        catch (Exception exception) {
            exception.printStackTrace();
            LocalApi local = (LocalApi) assetCanGetVideoApi(PlatformSupport.PLATFORM_LOCAL);
            // 从数据库获取信息
            filmography = local.baseInfoFromDb(docid, tvid, platform);
        }
        if (StringUtil.isEmpty(filmography.getId())){
            // 未指定docid, 则自动设置docid
            if (StringUtil.isEmpty(docid)){
                docid = EntityUtil.parseDocid(filmography);
            }
            filmography.setId(docid);
        }
        return filmography;
    }

    /**
     * 获取指定的 VideoAPI
     * @param platform
     * @return
     * @throws UnsupportServiceException
     */
    private VideoAPI assetCanGetVideoApi(String platform) throws UnsupportServiceException {
        VideoAPI api = videoApis.get(platform);
        if (api == null) {
            throw new UnsupportServiceException("参数有误");
        }
        return api;
    }
}
